home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / dflat2.zip / WINDOW.C < prev   
Text File  |  1991-04-19  |  17KB  |  519 lines

  1. /* ---------- window.c ------------- */
  2.  
  3. #include <stdio.h>
  4. #include <conio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <dos.h>
  8. #include "dflat.h"
  9.  
  10. WINDOW inFocus = NULLWND;
  11.  
  12. int foreground, background;   /* current video colors */
  13.  
  14. static void InsertTitle(WINDOW, char *);
  15. static void DisplayTitle(WINDOW, RECT);
  16.  
  17. /* --------- create a window ------------ */
  18. WINDOW CreateWindow(
  19.     CLASS class,              /* class of this window       */
  20.     char *ttl,                /* title or NULL              */
  21.     int left, int top,        /* upper left coordinates     */
  22.     int height, int width,    /* dimensions                 */
  23.     void *extension,          /* pointer to additional data */
  24.     WINDOW parent,            /* parent of this window      */
  25.     int (*wndproc)(struct window *,enum messages,PARAM,PARAM),
  26.     int attrib)               /* window attribute           */
  27. {
  28.     WINDOW wnd = malloc(sizeof(struct window));
  29.     get_videomode();
  30.     if (wnd != NULLWND)    {
  31.         int base;
  32.         /* ----- coordinates -1, -1 = center the window ---- */
  33.         if (left == -1)
  34.             wnd->rc.lf = (SCREENWIDTH-width)/2;
  35.         else
  36.             wnd->rc.lf = left;
  37.         if (top == -1)
  38.             wnd->rc.tp = (SCREENHEIGHT-height)/2;
  39.         else
  40.             wnd->rc.tp = top;
  41.         wnd->attrib = attrib;
  42.         if (ttl != NULL)
  43.             AddAttribute(wnd, TITLEBAR);
  44.         if (wndproc == NULL)
  45.             wnd->wndproc = classdefs[FindClass(class)].wndproc;
  46.         else
  47.             wnd->wndproc = wndproc;
  48.         /* ---- derive attributes of base classes ---- */
  49.         base = class;
  50.         while (base != -1)    {
  51.             int tclass = FindClass(base);
  52.             AddAttribute(wnd, classdefs[tclass].attrib);
  53.             base = classdefs[tclass].base;
  54.         }
  55.         if (parent && !TestAttribute(wnd, NOCLIP))    {
  56.             /* -- keep upper left within borders of parent -- */
  57.             wnd->rc.lf = max(wnd->rc.lf, GetClientLeft(parent));
  58.             wnd->rc.tp = max(wnd->rc.tp, GetClientTop(parent) +
  59.                 (TestAttribute(parent, HASMENUBAR) ? 1 : 0));
  60.         }
  61.         wnd->class = class;
  62.         wnd->extension = extension;
  63.         wnd->rc.rt = GetLeft(wnd)+width-1;
  64.         wnd->rc.bt = GetTop(wnd)+height-1;
  65.         wnd->ht = height;
  66.         wnd->wd = width;
  67.         wnd->title = ttl;
  68.         if (ttl != NULL)
  69.             InsertTitle(wnd, ttl);
  70.         wnd->next = wnd->prev = wnd->dFocus = NULLWND;
  71.         wnd->parent = parent;
  72.         wnd->videosave = NULL;
  73.         wnd->condition = ISRESTORED;
  74.         wnd->restored_attrib = 0;
  75.         wnd->RestoredRC = wnd->rc;
  76.         wnd->PrevKeyboard = wnd->PrevMouse = NULL;
  77.         wnd->DeletedText = NULL;
  78.         SendMessage(wnd, CREATE_WINDOW, 0, 0);
  79.         if (isVisible(wnd))
  80.             SendMessage(wnd, SHOW_WINDOW, 0, 0);
  81.     }
  82.     return wnd;
  83. }
  84.  
  85. /* -------- add a title to a window --------- */
  86. void AddTitle(WINDOW wnd, char *ttl)
  87. {
  88.     InsertTitle(wnd, ttl);
  89.     SendMessage(wnd, BORDER, 0, 0);
  90. }
  91.  
  92. /* ----- insert a title into a window ---------- */
  93. static void InsertTitle(WINDOW wnd, char *ttl)
  94. {
  95.     if ((wnd->title = malloc(strlen(ttl)+1)) != NULL)
  96.         strcpy(wnd->title, ttl);
  97. }
  98.  
  99. /* ------- write a character to a window at x,y ------- */
  100. void PutWindowChar(WINDOW wnd, int x, int y, int c)
  101. {
  102.     int x1 = GetClientLeft(wnd)+x;
  103.     int y1 = GetClientTop(wnd)+y;
  104.  
  105.     if (isVisible(wnd))    {
  106.         if (!TestAttribute(wnd, NOCLIP))    {
  107.             WINDOW wnd1 = GetParent(wnd);
  108.             while (wnd1 != NULLWND)    {
  109.                 /* --- clip character to parent's borders --- */
  110.                 if (x1 < GetClientLeft(wnd1)   ||
  111.                     x1 > GetClientRight(wnd1)  ||
  112.                     y1 > GetClientBottom(wnd1) ||
  113.                     y1 < GetClientTop(wnd1)    ||
  114.                     (y1 < GetTop(wnd1)+2 &&
  115.                             TestAttribute(wnd1, HASMENUBAR)))
  116.                         return;
  117.                 wnd1 = GetParent(wnd1);
  118.             }
  119.         }
  120.         if (x1 < SCREENWIDTH && y1 < SCREENHEIGHT)
  121.             wputch(wnd, c, x, y);
  122.     }
  123. }
  124.  
  125. static char line[161];
  126.  
  127. /* ----- clip line if it extends below the bottom of the
  128.              parent window ------ */
  129. static int clipbottom(WINDOW wnd, int y)
  130. {
  131.     if (!TestAttribute(wnd, NOCLIP))    {
  132.         WINDOW wnd1 = GetParent(wnd);
  133.         while (wnd1 != NULLWND)    {
  134.             if (GetClientTop(wnd)+y > GetBottom(wnd1))
  135.                 return TRUE;
  136.             wnd1 = GetParent(wnd1);
  137.         }
  138.     }
  139.     return GetClientTop(wnd)+y > SCREENHEIGHT;
  140. }
  141.  
  142. /* ------ clip the portion of a line that extends past the
  143.                      right margin of the parent window ----- */
  144. void clipline(WINDOW wnd, int x, char *ln)
  145. {
  146.     WINDOW pwnd = GetParent(wnd);
  147.     int x1 = strlen(ln);
  148.     int i = 0;
  149.  
  150.     if (!TestAttribute(wnd, NOCLIP))    {
  151.         while (pwnd != NULLWND)    {
  152.             x1 = GetRight(pwnd) - GetLeft(wnd) - x;
  153.             pwnd = GetParent(pwnd);
  154.         }
  155.     }
  156.     else if (GetLeft(wnd) + x > SCREENWIDTH)
  157.         x1 = SCREENWIDTH-GetLeft(wnd) - x;
  158.     /* --- adjust the clipping offset for color controls --- */
  159.     if (x1 < 0)
  160.         x1 = 0;
  161.     while (i < x1)    {
  162.         if ((unsigned char) ln[i] == CHANGECOLOR)
  163.             i += 3, x1 += 3;
  164.         else if ((unsigned char) ln[i] == RESETCOLOR)
  165.             i++, x1++;
  166.         else 
  167.             i++;
  168.     }
  169.     ln[x1] = '\0';
  170. }
  171.  
  172. /* ------ write a line to video window client area ------ */
  173. void writeline(WINDOW wnd, char *str, int x, int y, int pad)
  174. {
  175.     char wline[120];
  176.  
  177.     if (TestAttribute(wnd, HASBORDER))    {
  178.         x++;
  179.         y++;
  180.     }
  181.     if (!clipbottom(wnd, y))    {
  182.         char *cp;
  183.         int len;
  184.         int dif;
  185.  
  186.         memset(wline, 0, sizeof wline);
  187.         len = LineLength(str);
  188.         dif = strlen(str) - len;
  189.         strncpy(wline, str, ClientWidth(wnd) + dif);
  190.         if (pad)    {
  191.             cp = wline+strlen(wline);
  192.             while (len++ < ClientWidth(wnd)-x)
  193.                 *cp++ = ' ';
  194.         }
  195.         clipline(wnd, x, wline);
  196.         wputs(wnd, wline, x, y);
  197.     }
  198. }
  199.  
  200. /* -- write a line to video window (including the border) -- */
  201. void writefull(WINDOW wnd, char *str, int y)
  202. {
  203.     if (!clipbottom(wnd, y))    {
  204.         strcpy(line, str);
  205.         clipline(wnd, 0, line);
  206.         wputs(wnd, line, 0, y);
  207.     }
  208. }
  209.  
  210. /* -------- display a window's title --------- */
  211. static void DisplayTitle(WINDOW wnd, RECT rc)
  212. {
  213.     int tlen = min(strlen(wnd->title), WindowWidth(wnd)-2);
  214.     int tend = WindowWidth(wnd)-4;
  215.  
  216.     if (SendMessage(wnd, TITLE, 0, 0))    {
  217.         if (wnd == inFocus)    {
  218.             foreground = cfg.clr.InFocusTitleFG;
  219.             background = cfg.clr.InFocusTitleBG;
  220.         }
  221.         else    {
  222.             foreground = cfg.clr.TitleFG;
  223.             background = cfg.clr.TitleBG;
  224.         }
  225.         memset(line,' ',WindowWidth(wnd)-2);
  226.         if (wnd->condition != ISMINIMIZED)
  227.             strncpy(line + ((WindowWidth(wnd)-2 - tlen) / 2),
  228.                 wnd->title, tlen);
  229.         line[WindowWidth(wnd)-2] = '\0';
  230.         if (TestAttribute(wnd, CONTROLBOX))
  231.             line[1] = CONTROLBOXCHAR;
  232.         if (TestAttribute(wnd, MINMAXBOX))    {
  233.             switch (wnd->condition)    {
  234.                 case ISRESTORED:
  235.                     line[tend+1] = MAXPOINTER;
  236.                     line[tend]   = MINPOINTER;
  237.                     break;
  238.                 case ISMINIMIZED:
  239.                     line[tend+1] = MAXPOINTER;
  240.                     break;
  241.                 case ISMAXIMIZED:
  242.                     line[tend]   = MINPOINTER;
  243.                     line[tend+1] = RESTOREPOINTER;
  244.                     break;
  245.                 default:
  246.                     break;
  247.             }
  248.         }
  249.         line[RectRight(rc)+1] = '\0';
  250.         writeline(wnd, line+RectLeft(rc),
  251.                     RectLeft(rc), -1, FALSE);
  252.     }
  253. }
  254.  
  255. /* --- display right border shadow character of a window --- */
  256. static void near shadow_char(WINDOW wnd, int y)
  257. {
  258.     int fg = foreground;
  259.     int bg = background;
  260.     int x = WindowWidth(wnd);
  261.     int c = videochar(GetLeft(wnd)+x, GetTop(wnd)+y+1);
  262.  
  263.     if (TestAttribute(wnd, SHADOW) == 0)
  264.         return;
  265.     foreground = SHADOWFG;
  266.     background = BLACK;
  267.     PutWindowChar(wnd, x-1, y, c);
  268.     foreground = fg;
  269.     background = bg;
  270. }
  271.  
  272. /* --- display the bottom border shadow line for a window --- */
  273. static void near shadowline(WINDOW wnd, RECT rc)
  274. {
  275.     int i;
  276.     int y = GetBottom(wnd)+1;
  277.     if ((TestAttribute(wnd, SHADOW)) == 0)
  278.         return;
  279.     if (!clipbottom(wnd, WindowHeight(wnd)))    {
  280.         int fg = foreground;
  281.         int bg = background;
  282.         for (i = 0; i < WindowWidth(wnd); i++)
  283.             line[i] = videochar(GetLeft(wnd)+i+1, y);
  284.         line[i] = '\0';
  285.         foreground = SHADOWFG;
  286.         background = BLACK;
  287.         clipline(wnd, 1, line);
  288.         line[RectRight(rc)+3] = '\0';
  289.         wputs(wnd, line+RectLeft(rc), 1+RectLeft(rc),
  290.             WindowHeight(wnd));
  291.         foreground = fg;
  292.         background = bg;
  293.     }
  294. }
  295.  
  296. /* ------- display a window's border ----- */
  297. void RepaintBorder(WINDOW wnd, RECT *rcc)
  298. {
  299.     int y;
  300.     int lin, side, ne, nw, se, sw;
  301.     RECT rc, clrc;
  302.  
  303.     if (!TestAttribute(wnd, HASBORDER))
  304.         return;
  305.     if (rcc == NULL)    {
  306.         rc = SetRect(0, 0, WindowWidth(wnd)-1,
  307.                 WindowHeight(wnd)-1);
  308.         if (TestAttribute(wnd, SHADOW))    {
  309.             rc.rt++;
  310.             rc.bt++;
  311.         }
  312.     }
  313.     else
  314.         rc = *rcc;
  315.     clrc = rc;
  316.     /* -------- adjust the client rectangle ------- */
  317.     if (RectLeft(rc) == 0)
  318.         --clrc.rt;
  319.     else
  320.         --clrc.lf;
  321.     if (RectTop(rc) == 0)
  322.         --clrc.bt;
  323.     else
  324.         --clrc.tp;
  325.     RectRight(clrc) = min(RectRight(clrc), WindowWidth(wnd)-3);
  326.     RectBottom(clrc) =
  327.                      min(RectBottom(clrc), WindowHeight(wnd)-3);
  328.     if (wnd == inFocus)    {
  329.         lin  = FOCUS_LINE;
  330.         side = FOCUS_SIDE;
  331.         ne   = FOCUS_NE;
  332.         nw   = FOCUS_NW;
  333.         se   = FOCUS_SE;
  334.         sw   = FOCUS_SW;
  335.     }
  336.     else    {
  337.         lin  = LINE;
  338.         side = SIDE;
  339.         ne   = NE;
  340.         nw   = NW;
  341.         se   = SE;
  342.         sw   = SW;
  343.     }
  344.     line[WindowWidth(wnd)] = '\0';
  345.     /* ---------- window title ------------ */
  346.     if (RectTop(rc) == 0)
  347.         if (RectLeft(rc) < WindowWidth(wnd))
  348.             if (TestAttribute(wnd, TITLEBAR))
  349.                 DisplayTitle(wnd, clrc);
  350.     foreground = FrameForeground(wnd);
  351.     background = FrameBackground(wnd);
  352.     /* -------- top frame corners --------- */
  353.     if (RectTop(rc) == 0)    {
  354.         if (RectLeft(rc) == 0)
  355.             PutWindowChar(wnd, -1, -1, nw);
  356.         if (RectLeft(rc) < RectRight(rc))    {
  357.             if (RectRight(rc) >= WindowWidth(wnd)-1)
  358.                 PutWindowChar(wnd, WindowWidth(wnd)-2, -1, ne);
  359.  
  360.             if (TestAttribute(wnd, TITLEBAR) == 0)    {
  361.                 /* ----------- top line ------------- */
  362.                 memset(line,lin,WindowWidth(wnd)-1);
  363.                 line[RectRight(clrc)+1] = '\0';
  364.                 if (strlen(line+RectLeft(clrc)) > 1 ||
  365.                                TestAttribute(wnd, SHADOW) == 0)
  366.                     writeline(wnd, line+RectLeft(clrc),
  367.                             RectLeft(clrc), -1, FALSE);
  368.             }
  369.         }
  370.     }
  371.     /* ----------- window body ------------ */
  372.     for (y = 0; y < ClientHeight(wnd); y++)    {
  373.         int ch;
  374.         if (y >= RectTop(clrc) && y <= RectBottom(clrc))    {
  375.             if (RectLeft(rc) == 0)
  376.                 PutWindowChar(wnd, -1, y, side);
  377.             if (RectLeft(rc) < RectRight(rc))    {
  378.                 if (RectRight(rc) >= ClientWidth(wnd))    {
  379.                     if (TestAttribute(wnd, VSCROLLBAR))
  380.                         ch = (    y == 0 ? UPSCROLLBOX      :
  381.                                   y == WindowHeight(wnd)-3  ?
  382.                                        DOWNSCROLLBOX        :
  383.                                   y == wnd->VScrollBox      ?
  384.                                        SCROLLBOXCHAR        :
  385.                                        SCROLLBARCHAR );
  386.                     else
  387.                         ch = side;
  388.                     PutWindowChar(wnd, WindowWidth(wnd)-2,y,ch);
  389.                 }
  390.             }
  391.             if (RectRight(rc) == WindowWidth(wnd))
  392.                 shadow_char(wnd, y);
  393.         }
  394.     }
  395.     if (RectTop(rc) < RectBottom(rc) &&
  396.             RectBottom(rc) >= WindowHeight(wnd)-1)    {
  397.         /* -------- bottom frame corners ---------- */
  398.         if (RectLeft(rc) == 0)
  399.             PutWindowChar(wnd, -1, WindowHeight(wnd)-2, sw);
  400.         if (RectRight(rc) >= WindowWidth(wnd)-1)
  401.             PutWindowChar(wnd, WindowWidth(wnd)-2,
  402.                 WindowHeight(wnd)-2, se);
  403.         /* ----------- bottom line ------------- */
  404.         memset(line,lin,WindowWidth(wnd)-1);
  405.         if (TestAttribute(wnd, HSCROLLBAR))    {
  406.             line[0] = LEFTSCROLLBOX;
  407.             line[WindowWidth(wnd)-3] = RIGHTSCROLLBOX;
  408.             memset(line+1, SCROLLBARCHAR, WindowWidth(wnd)-4);
  409.             line[wnd->HScrollBox] = SCROLLBOXCHAR;
  410.         }
  411.         line[RectRight(clrc)+1] = '\0';
  412.         if (strlen(line+RectLeft(clrc)) > 1 ||
  413.                         TestAttribute(wnd, SHADOW) == 0)
  414.             writeline(wnd,
  415.                 line+RectLeft(clrc),
  416.                 RectLeft(clrc),
  417.                 WindowHeight(wnd)-2,
  418.                 FALSE);
  419.         if (RectRight(rc) == WindowWidth(wnd))
  420.             shadow_char(wnd, WindowHeight(wnd)-2);
  421.     }
  422.     if (RectBottom(rc) == WindowHeight(wnd))
  423.         /* ---------- bottom shadow ------------- */
  424.         shadowline(wnd, clrc);
  425. }
  426.  
  427. /* ------ clear the data space of a window -------- */
  428. void ClearWindow(WINDOW wnd, RECT *rcc, int clrchar)
  429. {
  430.     if (isVisible(wnd))    {
  431.         int y;
  432.         RECT rc;
  433.  
  434.         if (rcc == NULL)
  435.             rc = SetRect(0, 0, ClientWidth(wnd)-1,
  436.                 ClientHeight(wnd)-1);
  437.         else
  438.             rc = *rcc;
  439.         SetStandardColor(wnd);
  440.         memset(line, clrchar, RectWidth(rc));
  441.         line[RectWidth(rc)] = '\0';
  442.         for (y = RectTop(rc); y <= RectBottom(rc); y++)
  443.             writeline(wnd, line, RectLeft(rc), y, FALSE);
  444.     }
  445. }
  446.  
  447. /* -- adjust a window's rectangle to clip it to its parent -- */
  448. static RECT near AdjustRect(WINDOW wnd)
  449. {
  450.     RECT rc = wnd->rc;
  451.     if (TestAttribute(wnd, SHADOW))    {
  452.         RectBottom(rc)++;
  453.         RectRight(rc)++;
  454.     }
  455.     if (!TestAttribute(wnd, NOCLIP))    {
  456.         WINDOW pwnd = GetParent(wnd);
  457.         if (pwnd != NULLWND)    {
  458.             RectTop(rc) = max(RectTop(rc),
  459.                         GetClientTop(pwnd));
  460.             RectLeft(rc) = max(RectLeft(rc),
  461.                         GetClientLeft(pwnd));
  462.             RectRight(rc) = min(RectRight(rc),
  463.                         GetClientRight(pwnd));
  464.             RectBottom(rc) = min(RectBottom(rc),
  465.                         GetClientBottom(pwnd));
  466.         }
  467.     }
  468.     RectRight(rc) = min(RectRight(rc), SCREENWIDTH-1);
  469.     RectBottom(rc) = min(RectBottom(rc), SCREENHEIGHT-1);
  470.     RectLeft(rc) = min(RectLeft(rc), SCREENWIDTH-1);
  471.     RectTop(rc) = min(RectTop(rc), SCREENHEIGHT-1);
  472.     return rc;
  473. }
  474.  
  475. /* --- get the video memory that is to be used by a window -- */
  476. void GetVideoBuffer(WINDOW wnd)
  477. {
  478.     RECT rc;
  479.     int ht;
  480.     int wd;
  481.  
  482.     rc = AdjustRect(wnd);
  483.     ht = RectBottom(rc) - RectTop(rc) + 1;
  484.     wd = RectRight(rc) - RectLeft(rc) + 1;
  485.     wnd->videosave = realloc(wnd->videosave, (ht * wd * 2));
  486.     get_videomode();
  487.     if (wnd->videosave != NULL)
  488.         getvideo(rc, wnd->videosave);
  489. }
  490.  
  491. /* --- restore the video memory that was used by a window --- */
  492. void RestoreVideoBuffer(WINDOW wnd)
  493. {
  494.     if (wnd->videosave != NULL)    {
  495.         RECT rc = AdjustRect(wnd);
  496.         storevideo(rc, wnd->videosave);
  497.         free(wnd->videosave);
  498.         wnd->videosave = NULL;
  499.     }
  500. }
  501.  
  502. /* ------- compute the logical line length of a window ------ */
  503. int LineLength(char *ln)
  504. {
  505.     int len = strlen(ln);
  506.     char *cp = ln;
  507.     while ((cp = strchr(cp, CHANGECOLOR)) != NULL)    {
  508.         cp++;
  509.         len -= 3;
  510.     }
  511.     cp = ln;
  512.     while ((cp = strchr(cp, RESETCOLOR)) != NULL)    {
  513.         cp++;
  514.         --len;
  515.     }
  516.     return len;
  517. }
  518.  
  519.